Disk+[UIImage].swift 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import Foundation
  2. import UIKit
  3. public extension Disk {
  4. /// Save an array of images to disk
  5. ///
  6. /// - Parameters:
  7. /// - value: array of images to store
  8. /// - directory: user directory to store the images in
  9. /// - path: folder location to store the images (i.e. "Folder/")
  10. /// - Throws: Error if there were any issues creating a folder and writing the given images to it
  11. static func save(_ value: [UIImage], to directory: Directory, as path: String) throws {
  12. do {
  13. let folderUrl = try createURL(for: path, in: directory)
  14. try createSubfoldersBeforeCreatingFile(at: folderUrl)
  15. try FileManager.default.createDirectory(at: folderUrl, withIntermediateDirectories: false, attributes: nil)
  16. for i in 0 ..< value.count {
  17. let image = value[i]
  18. var imageData: Data
  19. var imageName = "\(i)"
  20. var pngData: Data?
  21. var jpegData: Data?
  22. #if swift(>=4.2)
  23. if let data = image.pngData() {
  24. pngData = data
  25. } else if let data = image.jpegData(compressionQuality: 1) {
  26. jpegData = data
  27. }
  28. #else
  29. if let data = UIImagePNGRepresentation(image) {
  30. pngData = data
  31. } else if let data = UIImageJPEGRepresentation(image, 1) {
  32. jpegData = data
  33. }
  34. #endif
  35. if let data = pngData {
  36. imageData = data
  37. imageName = imageName + ".png"
  38. } else if let data = jpegData {
  39. imageData = data
  40. imageName = imageName + ".jpg"
  41. } else {
  42. throw createError(
  43. .serialization,
  44. description: "Could not serialize UIImage \(i) in the array to Data.",
  45. failureReason: "UIImage \(i) could not serialize to PNG or JPEG data.",
  46. recoverySuggestion: "Make sure there are no corrupt images in the array."
  47. )
  48. }
  49. let imageUrl = folderUrl.appendingPathComponent(imageName, isDirectory: false)
  50. try imageData.write(to: imageUrl, options: .atomic)
  51. }
  52. } catch {
  53. throw error
  54. }
  55. }
  56. /// Append an image to a folder
  57. ///
  58. /// - Parameters:
  59. /// - value: image to store to disk
  60. /// - path: folder location to store the image (i.e. "Folder/")
  61. /// - directory: user directory to store the image file in
  62. /// - Throws: Error if there were any issues writing the image to disk
  63. static func append(_ value: UIImage, to path: String, in directory: Directory) throws {
  64. do {
  65. if let folderUrl = try? getExistingFileURL(for: path, in: directory) {
  66. let fileUrls = try FileManager.default.contentsOfDirectory(
  67. at: folderUrl,
  68. includingPropertiesForKeys: nil,
  69. options: []
  70. )
  71. var largestFileNameInt = -1
  72. for i in 0 ..< fileUrls.count {
  73. let fileUrl = fileUrls[i]
  74. if let fileNameInt = fileNameInt(fileUrl) {
  75. if fileNameInt > largestFileNameInt {
  76. largestFileNameInt = fileNameInt
  77. }
  78. }
  79. }
  80. let newFileNameInt = largestFileNameInt + 1
  81. var imageData: Data
  82. var imageName = "\(newFileNameInt)"
  83. var pngData: Data?
  84. var jpegData: Data?
  85. #if swift(>=4.2)
  86. if let data = value.pngData() {
  87. pngData = data
  88. } else if let data = value.jpegData(compressionQuality: 1) {
  89. jpegData = data
  90. }
  91. #else
  92. if let data = UIImagePNGRepresentation(value) {
  93. pngData = data
  94. } else if let data = UIImageJPEGRepresentation(value, 1) {
  95. jpegData = data
  96. }
  97. #endif
  98. if let data = pngData {
  99. imageData = data
  100. imageName = imageName + ".png"
  101. } else if let data = jpegData {
  102. imageData = data
  103. imageName = imageName + ".jpg"
  104. } else {
  105. throw createError(
  106. .serialization,
  107. description: "Could not serialize UIImage to Data.",
  108. failureReason: "UIImage could not serialize to PNG or JPEG data.",
  109. recoverySuggestion: "Make sure image is not corrupt."
  110. )
  111. }
  112. let imageUrl = folderUrl.appendingPathComponent(imageName, isDirectory: false)
  113. try imageData.write(to: imageUrl, options: .atomic)
  114. } else {
  115. let array = [value]
  116. try save(array, to: directory, as: path)
  117. }
  118. } catch {
  119. throw error
  120. }
  121. }
  122. /// Append an array of images to a folder
  123. ///
  124. /// - Parameters:
  125. /// - value: images to store to disk
  126. /// - path: folder location to store the images (i.e. "Folder/")
  127. /// - directory: user directory to store the images in
  128. /// - Throws: Error if there were any issues writing the images to disk
  129. static func append(_ value: [UIImage], to path: String, in directory: Directory) throws {
  130. do {
  131. if let _ = try? getExistingFileURL(for: path, in: directory) {
  132. for image in value {
  133. try append(image, to: path, in: directory)
  134. }
  135. } else {
  136. try save(value, to: directory, as: path)
  137. }
  138. } catch {
  139. throw error
  140. }
  141. }
  142. /// Retrieve an array of images from a folder on disk
  143. ///
  144. /// - Parameters:
  145. /// - path: path of folder holding desired images
  146. /// - directory: user directory where images' folder was created
  147. /// - type: here for Swifty generics magic, use [UIImage].self
  148. /// - Returns: [UIImage] from disk
  149. /// - Throws: Error if there were any issues retrieving the specified folder of images
  150. static func retrieve(_ path: String, from directory: Directory, as _: [UIImage].Type) throws -> [UIImage] {
  151. do {
  152. let url = try getExistingFileURL(for: path, in: directory)
  153. let fileUrls = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [])
  154. let sortedFileUrls = fileUrls.sorted(by: { (url1, url2) -> Bool in
  155. if let fileNameInt1 = fileNameInt(url1), let fileNameInt2 = fileNameInt(url2) {
  156. return fileNameInt1 <= fileNameInt2
  157. }
  158. return true
  159. })
  160. var images = [UIImage]()
  161. for i in 0 ..< sortedFileUrls.count {
  162. let fileUrl = sortedFileUrls[i]
  163. let data = try Data(contentsOf: fileUrl)
  164. if let image = UIImage(data: data) {
  165. images.append(image)
  166. }
  167. }
  168. return images
  169. } catch {
  170. throw error
  171. }
  172. }
  173. }